home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <limits.h>
- #include <time.h>
- #include <sys/stat.h>
- #include "dialog.h"
- #include "diadef.h"
- #include "internal.h"
- #include "cmdsock.h"
- #include "dialog.m"
- #include "../paths.h"
- #include "../userconf/userconf.h"
- #include "../netconf/netconf.h"
-
- static char *html_host = NULL;
- static int html_cli; // Handle use to talk back to client
- static int port;
- static int target_level;
- static int history_level;
- static int debug;
- static int html_java; // Produce HTML code or command for the java
- // front end
- static HTML_VARVAL *curvars;
- static MENU_STATUS html_submit; // Button action to process
- static int html_postdone; // Did the POST was processed
- static int html_drawdone; // Insure that we draw a html page only once
- static char html_popup=0;
-
- struct LEVEL_INFO{
- MENU_STATUS status;
- SSTRING key;
- SSTRING title;
- };
- static LEVEL_INFO tblevel[20];
- static int level = 0;
-
- static const char *html_getval (int lev, const char *key)
- {
- char bufkey[200];
- sprintf (bufkey,"%d_%s",lev,key);
- const char *ret = "";
- if (curvars != NULL) ret = curvars->getval(bufkey);
- return ret;
-
- }
-
- /*
- Get the new value of a field
- */
- const char *html_getval (const char *key)
- {
- return html_getval (level,key);
- }
-
- /*
- Check if a button exist as a variable (the user has clicked on it)
- */
- static int html_butexist (const char *key)
- {
- int ret = 0;
- if (curvars != NULL) ret = curvars->exist(key);
- return ret;
- }
-
- static void html_reset()
- {
- // Variable a simply never forgotten. Some primitive form
- // of garbage collection in varval.c take care of too old entries
- curvars = NULL;
- html_postdone = 0;
- html_drawdone = 0;
- html_popup=0;
- }
-
- /*
- Get the original value of a field
- */
- const char *html_getoldval (const char *key)
- {
- char oldkey[100];
- sprintf (oldkey,"CUR_%s",key);
- return html_getval (oldkey);
- }
-
- /*
- Generate a <input command to define a field
- */
- void html_defvar (
- const char *type,
- const char *name,
- const char *value,
- const char *opt)
- {
- html_printf ("<input type=%s name=\"%d_%s\" value=\"%s\" %s>\n"
- ,type,level,name,value,opt);
- }
- void html_defvar (
- const char *type,
- const char *name,
- int value,
- const char *opt)
- {
- char tmp[20];
- sprintf (tmp,"%d",value);
- html_defvar (type,name,tmp,opt);
- }
- /*
- Generate a <input command to define the current value of a field
- */
- void html_defvarcur (
- const char *name,
- const char *value)
- {
- html_printf ("<input type=hidden name=\"%d_CUR_%s\" value=\"%s\">\n"
- ,level,name,value);
- }
- void html_defvarcur (
- const char *name,
- int value)
- {
- char tmp[20];
- sprintf (tmp,"%d",value);
- html_defvarcur (name,tmp);
- }
-
-
- static char *html_buf;
- static int html_len;
- static int html_maxlen;
-
- void html_printf (const char *ctl, ...)
- {
- va_list list;
- va_start (list,ctl);
- char buf[1000];
- int len = vsprintf (buf,ctl,list);
- va_end (list);
- if (html_len + len > html_maxlen){
- html_maxlen += 5000;
- html_buf = (char*)realloc(html_buf,html_maxlen);
- }
- strcpy (html_buf+html_len,buf);
- html_len += len;
- }
-
- void html_flush ()
- {
- if (html_len > 0){
- write (html_cli,html_buf,html_len);
- html_len = 0;
- }
- }
-
- /*
- Record the host name and port number to encode in URLs
- */
- void html_sethost (const char *_hostname, int _port)
- {
- free (html_host);
- html_host = strdup(_hostname);
- port = _port;
- }
-
- static char KEY_ACCEPT[]="accept";
- static char KEY_DEL[]="del";
- static char KEY_OK[]="ok";
- static char KEY_ADD[]="add";
- static char KEY_EDIT[]="edit";
- static char KEY_YES[]="yes";
- static char KEY_NO[]="no";
-
- /*
- Format a path to a sub-meny entry
- */
- static void html_setpath_level(char *path, int upto)
- {
- char *pt = path;
- LEVEL_INFO *ptl = tblevel;
- for (int i=0; i<upto; i++,ptl++){
- const char *key = KEY_OK;
- if (ptl->status == MENU_DEL){
- key = KEY_DEL;
- }else if (ptl->status == MENU_ACCEPT){
- key = KEY_ACCEPT;
- }else if (ptl->status == MENU_ADD){
- key = KEY_ADD;
- }else if (ptl->status == MENU_EDIT){
- key = KEY_EDIT;
- }else if (ptl->status == MENU_YES){
- key = KEY_YES;
- }else if (ptl->status == MENU_NO){
- key = KEY_NO;
- }
- pt += sprintf (pt,"%s,%s/",key,ptl->key.get());
- }
- *pt = '\0';
- }
- /*
- Format a context to a sub-meny entry
- */
- static void html_setcontext_level(char *path, int upto)
- {
- char *pt = path;
- LEVEL_INFO *ptl = tblevel;
- for (int i=0; i<upto; i++,ptl++){
- pt += sprintf (pt,"%s/",ptl->key.get());
- }
- *pt = '\0';
- }
- /*
- Format a path to a sub-meny entry
- */
- static void html_setpath(char *path)
- {
- html_setpath_level (path,level);
- }
- /*
- Set a url pointing to a sub-menu entry
- */
- void html_setaref (
- const char *key, // Key for the url (path indeed)
- const char *text) // Highlit text
- {
-
- char path[PATH_MAX];
- html_setpath (path);
- html_printf ("<A HREF=\"http://%s:%d/html:/%sok,%s\">%s</A>"
- ,html_host,port,path,key,text);
- }
-
-
- /*
- Format a message suitable as a path component of a URL.
- Space are transformed to ==.
- */
- void html_formatkey (char *key, const char *ctl, ...)
- {
- va_list list;
- va_start (list,ctl);
- char buf[1000];
- vsprintf (buf,ctl,list);
- va_end (list);
- char *pt = buf;
- while (*pt != '\0'){
- char carac = *pt++;
- if (carac == ' ' || carac == '/'){
- *key++ = '=';
- *key++ = '=';
- }else{
- *key++ = carac;
- }
- }
- *key = '\0';
- }
-
- /*
- Send the header of the html document.
- */
- static void html_sendintro(
- const char *content_type,
- int length, // Length or -1
- int expires) // How much seconds this document is expected to
- // be valid
- {
- time_t tim = time(NULL);
-
- html_printf ("HTTP/1.0 200 Document follows\r\n");
- html_printf ("MIME-Version: 1.0\r\n");
- extern char *revision;
- html_printf ("Server: linuxconf/%s\r\n",revision);
- char buf[200];
- tim += expires;
- strcpy (buf,asctime(localtime(&tim)));
- strip_end (buf);
- html_printf ("Date: %s\r\n",buf);
- html_printf ("Content-Type: %s\r\n",content_type);
- if (length != -1){
- html_printf ("Content-Length: %d\r\n",length);
- }
- html_printf ("Expires: %s\r\n",buf);
- html_printf ("Last-Modified: %s\r\n",buf);
- html_printf ("\r\n");
- }
-
- static CMDSOCK *cmd = NULL;
- /*
- Indicate that the html page has been sent and the connection can
- be closed.
- */
- static void html_setdone()
- {
- html_drawdone = 1;
- html_flush ();
- if (cmd != NULL) cmd->closecli (html_cli);
- }
-
-
- /*
- Is called when a password is needed.
- The proper information is sent to the www browser requesting such
- a pawwword.
-
- The web browser will retransmit this password for the rest of
- the session.
- */
- void html_needpasswd()
- {
- html_printf ("HTTP/1.0 401 Unauthorized\r\n");
- time_t tim = time(NULL);
- char buf[200];
- strcpy (buf,asctime(localtime(&tim)));
- strip_end (buf);
- html_printf ("Date: %s\r\n",buf);
- extern char *revision;
- html_printf ("Server: linuxconf/%s\r\n",revision);
- html_printf ("WWW-Authenticate: Basic realm=\"root\"\r\n");
- html_printf ("Content-type: text/html\r\n");
- html_printf ("\r\n"
- "<HEAD><TITLE>Authorization Required</TITLE></HEAD>\r\n"
- "<BODY><H1>Authorization Required</H1>\r\n"
- "This server could not verify that you\r\n"
- "are authorized to access the document you\r\n"
- "requested. Either you supplied the wrong\r\n"
- "credentials (e.g., bad password), or your\r\n"
- "browser doesn't understand how to supply\r\n"
- "the credentials required.<P>\r\n"
- "</BODY>\r\n"
- );
- html_setdone();
- }
- PRIVATE void DIALOG::html_draw_top()
- {
- html_sendintro ("text/html",-1,15);
- html_printf (
- "<HTML>\n"
- "<HEAD>\n"
- "<TITLE>%s:%s</TITLE>\n"
- "</HEAD>\n"
- "<BODY>\n",html_host,title.get());
- for (int i=0; i<history_level; i++){
- char path[PATH_MAX];
- html_setpath_level (path,i);
- char indent[20];
- memset (indent,'.',sizeof(indent));
- indent[i] = '\0';
- html_printf ("<a href=\"/html:/%s\">%s%s</a>\n<br>\n"
- ,path
- ,indent
- ,tblevel[i].title.get());
- }
- if (level > 0) html_printf ("<hr>\n");
- }
-
- PRIVATE void DIALOG::html_draw_intro()
- {
- if (!icon.is_empty()){
- html_printf ("<img src=/images:images/%s.gif>\n",icon.get());
- }
- if (!intro.is_empty()){
- html_printf ("<PRE>%s</PRE>\n\n<hr>\n",intro.get());
- }
- }
-
- PRIVATE void DIALOG::html_draw_fields()
- {
- int lastf = getnb();
- for (int i=0; i<lastf; i++) getitem(i)->html_draw (i);
- }
- PRIVATE void DIALOG::html_draw_form()
- {
- char path[300];
- html_setpath_level (path,target_level);
- html_printf ("<form method=post action=/html:/%s>\n",path);
- html_printf ("<CENTER>\n");
- html_printf ("<TABLE border=1>\n");
- if (curvars != NULL){
- // Define variable for previous level
- int n = curvars->getnb();
- for (int i=0; i<n; i++){
- const char *name = curvars->getvar(i);
- if (isdigit(name[0]) && atoi(name)<level){
- html_printf ("<input type=hidden name=\"%s\" value=\"%s\">\n"
- ,name,curvars->getval(i));
- }
- }
- }
- html_draw_fields();
- html_printf ("</TABLE>\n");
- html_printf ("</CENTER>\n");
- buttons->html_draw ();
- html_printf ("</form>\n");
- }
- PRIVATE void DIALOG::html_draw_end()
- {
- html_printf ("</BODY>\n</HTML>\n");
- }
- /*
- Draw the complete dialog including a subdialog (error, password request)
- */
-
- PRIVATE void DIALOG::html_draw (DIALOG *spc)
- {
- /* #Specification: html mode / strategy / back on our feet
- Maybe this is an already visited dialog. This has been visited
- along the path followed while running through tblevel[]. While
- doing so, we have stamp dialog title in each level (in
- DIALOG::edithtml()). We will search now to see if we can find
- this dialog title in tblevel and correct target_level accordingly.
-
- This situation happen with the following case:
-
- #
- -The user is visiting one menu
- -he selects one dialog
- -he fills some fields and click on the "accept" button.
- -A subdialog is poped
- -The user fills it
- -After some sub-sub-dialogs the job is done and we are
- back to the original menu.
- #
-
- All these steps have collected a longer and longer html path.
- Each level of the path have captured the variable states used to
- go the next. So we have a very long path, but we have to
- fall on our feet again with a short path.
- */
- for (int i=0; i<target_level; i++){
- if (tblevel[i].title.cmp(title) ==0){
- target_level = i;
- level = i;
- break;
- }
- }
- html_draw_top();
- if (spc != NULL){
- spc->html_draw_intro();
- spc->html_draw_fields();
- html_printf ("<hr>\n");
- }
- html_draw_intro();
- html_draw_form();
- html_draw_end();
- }
- /*
- Draw the complete dialog
- */
-
- PRIVATE void DIALOG::html_draw ()
- {
- html_draw(NULL);
- }
- /*
- Load all field of the dialog with the received value
- and check that everything is valid
- Return -1 if any error.
- */
-
- PRIVATE int DIALOG::html_validate ()
- {
- int ret = 0;
- int lastf = getnb();
- for (int i=0; i<lastf; i++) ret |= getitem(i)->html_validate (i);
- return ret;
- }
-
- PUBLIC void BUTTONS_INFO::html_draw()
- {
- for (int i=0; i<nb; i++){
- MENU_STATUS code = tbret[i];
- const char *name = "nil";
- if (code == MENU_HELP){
- html_printf ("<a href=\"http:/help:%s.html\">"
- "<img src=/images:images/%s.gif></a>\n"
- ,helpfile.get()+strlen(USR_LIB_LINUXCONF)+1
- ,tb[i]);
- }else{
- if (code == MENU_CANCEL
- || code == MENU_QUIT
- || code == MENU_OK){
- continue; // Those buttons are useless in html mode
- }else if (code == MENU_ACCEPT){
- name = KEY_ACCEPT;
- }else if (code == MENU_ADD){
- name = KEY_ADD;
- }else if (code == MENU_SAVE){
- name = "save";
- }else if (code == MENU_DEL){
- name = KEY_DEL;
- }else if (code == MENU_EDIT){
- name = KEY_EDIT;
- }else if (code == MENU_YES){
- name = KEY_YES;
- }else if (code == MENU_NO){
- name = KEY_NO;
- }else{
- printf ("old button\n");
- #if 0
- char path[PATH_MAX];
- html_setpath (path);
- html_printf ("<a href=\"http://%s:%d/button:%s:%s\">%s</a>\n"
- ,html_host
- ,port
- ,tb[i]
- ,path
- ,tb[i]);
- #endif
- }
- html_printf ("<input type=image name=%s "
- "src=/images:images/%s.gif>\n"
- ,name,tb[i]);
- }
- }
- }
-
- static DIALOG *html_postdialog;
-
- void html_forgetdialog (DIALOG *dia)
- {
- if (dia == html_postdialog){
- html_postdialog = NULL;
- #if 0
- if (!html_drawdone){
- // The next time we will get in edithtml, level is still equal
- // to target_level, so html_draw will be called
- // providing the next page to www user. This is a hack.
- // After an accept, we are back to the previous menu
- target_level--;
- level--;
- }
- #endif
- }
- }
-
- /* #Specification: html mode / general strategy
- Here is a basic explanation of the way linuxconf manage html page
- while not being that much http/html aware.
-
- Some fact:
-
- #
- -Linuxconf is a classical modal program. Mostly, only one dialog has
- the focus at a time. Further, in linuxconf, there is generally
- only one dialog at once. This is acceptable for admin tasks anyway.
- -html mode work with the concept of hope. You send a page to a
- user and he may click on a button one day or never. You better
- not wait for it. So good for a modal program.
- #
-
- The strategy is simple. Linuxconf is always waiting at the
- top level of the menu hierachy for an html request. Each request
- contain a path (using /'s) allowing linuxconf to navigate
- in the menu hisrarchy up to a certain "level". At this point
- linuxconf simply draw the dialog or menu and ... get back
- to the top level.
-
- This behavior of always getting back is trigger by returning
- MENU_ESCAPE, so each part of linuxconf must be "ESCAPE" aware, which
- is good anyway.
-
- So when we get a path, we parse it and store it in a table
- and note the target_level.
-
- Important assumption here:
-
- All dialog with input are preceded in the hierarchy by menus.
- This make sens anyway. This disable support for popup dialog
- however.
-
- So we parse and store the path and lauch linuxconf from the top
- level menu. While navigating in its code, linuxconf draw menus
- (not really) and wait for input (not really also). If this
- menu is not of the proper level, the path information will be
- used as a key to identify which menu item was choosen. A MENU_OK
- is then returned and linuxconf continue to navigate further into
- sub-sub-menus (In fact the exact button returned is contain
- in the path). At some point, it crosses the target level.
-
- At the target level, there is two cases:
-
- Either this is GET or a POST. If this is a GET, we draw the dialog
- and escape away to the main loop. If this is a POST, then we
- load all the fields of the dialog with the values received from
- the POST.
-
- Based on some special values, we know which buttons was hit and
- return appropriatly MENU_ACCEPT, MENU_ADD and so on to the
- application. Three things may happen. Either there is some error
- message (The application identify those with html_setpopup())
- or linuxconf is happy and exited to the previous level menu (Leaving
- this dialog screen) or linuxconf provide a sub-dialog asking for
- more info.
-
- Most of the logic here is controlled by the DIALOG::edithtml()
- function.
- */
-
- /*
- Record that the next DIALOG object is a popup dialog (error message)
- */
- void html_setpopup()
- {
- html_popup = 1;
- }
- PRIVATE MENU_STATUS DIALOG::edithtml(int &nof)
- {
- MENU_STATUS ret = MENU_ESCAPE;
- if (!html_drawdone){
- static SSTRING top_str;
- static SSTRING bottom_str;
- if (level == target_level){
- static MENU_STATUS was_button; // Was it a POST with the
- // button accept
- if (curvars != NULL && !html_postdone){
- //html_postdialog = this;
- if (html_validate() != -1){
- // Those names need not be translated
- // see BUTTONS_INFO::html_draw()
- if (html_butexist("ok.x")){
- ret = MENU_OK;
- }else if (html_butexist("accept.x")){
- ret = MENU_ACCEPT;
- }else if (html_butexist("add.x")){
- ret = MENU_ADD;
- }else if (html_butexist("edit.x")){
- ret = MENU_EDIT;
- }else if (html_butexist("del.x")){
- ret = MENU_DEL;
- }else if (html_butexist("save.x")){
- ret = MENU_SAVE;
- }else if (html_butexist("yes.x")){
- ret = MENU_YES;
- }else if (html_butexist("no.x")){
- ret = MENU_NO;
- }else{
- if (debug) fprintf (stderr,"Invalid button\n");
- ret = MENU_CANCEL;
- }
- was_button = ret;
- html_postdone = 1;
- html_draw_top();
- top_str.setfrom (html_buf);
- html_len = 0;
- html_draw_intro();
- html_draw_form();
- html_draw_end();
- bottom_str.setfrom(html_buf);
- html_len = 0;
- }else{
- html_printf ("500 %s\r\n"
- ,MSG_U(E_MISMATCH,"dialog state mismatch"));
- html_setdone();
- }
- }else{
- if (curvars != NULL){
- if (html_popup){
- top_str.copy (html_buf);
- html_len = strlen (html_buf);
- html_draw_intro();
- html_draw_fields();
- bottom_str.copy (html_buf+html_len);
- html_len = strlen (html_buf);
- }else{
- if (was_button == MENU_ACCEPT && 0){
- // We have accepted so we get back to
- // previous menu
- target_level--;
- level--;
- }else{
- tblevel[level].status = was_button;
- target_level++;
- level++;
- }
- html_draw();
- }
- }else{
- html_draw();
- }
- html_setdone();
- }
- }else if (level < target_level){
- LEVEL_INFO *pt = tblevel + level;
- pt->title.setfrom (title);
- int n = getnb();
- nof = -1;
- for (int i=0; i<n; i++){
- char key[PATH_MAX];
- getitem(i)->format_htmlkey(key,i);
- printf ("Compare :%s: :%s:\n",key,pt->key.get());
- if (pt->key.cmp(key)==0){
- nof = i;
- break;
- }
- }
- if (nof == -1
- && pt->status == MENU_OK){
- html_printf ("500 %s\r\n",MSG_U(E_IVLDURL,"Invalid URL\n"));
- printf ("Et ne trouve pas %d\n",pt->status);
- html_setdone();
- }else{
- ret = pt->status;
- {
- #if 0
- // We have to reestablish the context at the moment
- // of the original POST which has happen at this
- // level in a previous session
- char context[200];
- html_setcontext_level(context,level);
- HTML_VARVAL *lv = varval_get(context);
- if (lv != NULL){
- HTML_VARVAL *cur = curvars;
- curvars = lv;
- if (html_validate() == -1){
- html_printf ("500 %s\r\n",MSG_R(E_MISMATCH));
- html_setdone();
- }
- curvars = cur;
- }
- #else
- printf ("Intermediate validate level %d %d\n",level,ret);
- if (html_validate() == -1){
- html_printf ("500 %s\r\n",MSG_R(E_MISMATCH));
- html_setdone();
- }
- printf ("Intermediate validate level %d end\n",level);
- #endif
- }
-
- }
- level++;
- }
- }
- return ret;
- }
-
- static void html_parsepath(char *pt)
- {
- if (debug) fprintf (stderr,"Parse path :%s:\n",pt);
- int len = strlen(pt);
- if (len > 0 && pt[len-1] == '/') pt[len-1] = '\0';
- history_level = level = target_level = 0;
- if (pt[0] == '/') pt++;
- while (*pt != '\0'){
- char *split = strchr (pt,'/');
- if (split != NULL) *split++ = '\0';
- char *comma = strchr(pt,',');
- if (comma != NULL){
- *comma++ = '\0';
- if (comma[0] != '\0') history_level++;
- }
- LEVEL_INFO *ptl = &tblevel[target_level++];
- ptl->key.setfrom (comma);
- if (strcmp(pt,KEY_OK)==0){
- ptl->status = MENU_OK;
- }else if (strcmp(pt,KEY_ACCEPT)==0){
- ptl->status = MENU_ACCEPT;
- }else if (strcmp(pt,KEY_ADD)==0){
- ptl->status = MENU_ADD;
- }else if (strcmp(pt,KEY_DEL)==0){
- ptl->status = MENU_DEL;
- }else if (strcmp(pt,KEY_YES)==0){
- ptl->status = MENU_YES;
- }else if (strcmp(pt,KEY_NO)==0){
- ptl->status = MENU_NO;
- }else if (strcmp(pt,KEY_EDIT)==0){
- ptl->status = MENU_EDIT;
- }
- if (split != NULL){
- pt = split;
- }else{
- break;
- }
- }
- }
- static void html_dbglog (const char *title, const char *str)
- {
- FILE *f = fopen ("/tmp/li.dbg","a");
- if (f != NULL){
- fprintf (f,"======%s=======\n",title);
- fputs (str,f);
- fclose (f);
- }
- }
-
- static char hextoi (char asc)
- {
- return isdigit(asc) ? asc - '0' : (toupper(asc) - 'A') + 10;
- }
-
- static const char *html_decode (const char *str, char *buf)
- {
- char *pt = buf;
- while (*str != '\0' && *str != '\n'){
- if (*str == '%'){
- str++;
- *pt++ = hextoi(*str++) * 16 + hextoi(*str++);
- }else if (*str == '+'){
- *pt++ = ' ';
- str++;
- }else{
- *pt++ = *str++;
- }
- }
- *pt = '\0';
- strip_end (buf);
- if (*str == '\n') str++;
- return str;
- }
-
- static void html_parsevar (const char *buf)
- {
- {
- char context[200];
- html_setcontext_level(context,target_level);
- curvars = new HTML_VARVAL(context);
- }
- while (1){
- char *pt = strchr(buf,'=');
- if (pt == NULL){
- break;
- }else{
- *pt++ = '\0';
- char *end = strchr(pt,'&');
- if (end != NULL){
- *end++ = '\0';
- }
- char var[200];
- char val[2000];
- html_decode (buf,var);
- html_decode (pt,val);
- curvars->add (var,val);
- if (end == NULL) break;
- buf = end;
- }
- }
- }
- /*
- Parse a potentially completed header.
- Extract the "get" command or "post" command.
-
- Return -1 if any error.
- Return 0 if the header was not completed
- Return 1 if the header was completed
- */
- static int html_parse (
- const char *str,
- char *file_request, // Will contain a file to transmit to the client
- char *username, // Will hold the username
- char *password, // and password provided by the browser
- HELP_FILE &intro)
- {
- unsigned expected_length = 0;
- int html_post = 0;
- int ret = 0;
- int get_ok = 0;
- file_request[0] = '\0';
- html_java = 0;
- html_submit = MENU_NULL;
- username[0] = '\0';
- password[0] = '\0';
- while (*str != '\0'){
- char buf[10000];
- str = html_decode (str,buf);
- if (buf[0] == '\0'){
- if (get_ok){
- html_reset();
- if (html_post){
- char t[100];
- sprintf (t,"expe %u, got %u\n",expected_length,strlen(str));
- html_dbglog ("detail",t);
- if (strlen(str) >= expected_length){
- strcpy (buf,str);
- html_parsevar (buf);
- ret = 1;
- }
- break;
- }else{
- ret = 1;
- }
- }else{
- ret = -1;
- }
- }else{
- char cmd[200];
- char *pt = str_copyword (cmd,buf);
- strupr (cmd);
- int is_get = strcmp(cmd,"GET")==0;
- int is_post = strcmp(cmd,"POST")==0;
- if (is_get || is_post){
- pt = str_skip (pt);
- char path[1000];
- char parm[1000];
- parm[0] = '\0';
- str_copyword (path,pt);
- char *ptparm = strchr(path,'?');
- if (ptparm != NULL){
- *ptparm++ = '\0';
- strcpy (parm,ptparm);
- }
- if (strncmp(path,"/help:",6)==0){
- strcpy (file_request,path+6);
- }else if (strncmp(path,"/images:",8)==0){
- strcpy (file_request,path+8);
- }else if (strncmp(path,"/java:",6)==0){
- html_java = 1;
- html_parsepath(path+6);
- }else if (strncmp(path,"/html:",6)==0){
- html_parsepath(path+6);
- #if 0
- }else if (strncmp(path,"/button:",8)==0){
- char *pt = path + 8;
- // No need to make this translatable
- static struct BUT_LKP{
- const char *name;
- MENU_STATUS but;
- }tb[]={
- {"add", MENU_ADD},
- {"del", MENU_DEL},
- {"save", MENU_ADD},
- {"accept", MENU_ACCEPT},
- };
- BUT_LKP *ptb = tb;
- for (unsigned i=0; i<sizeof(tb)/sizeof(tb[0])
- ; i++, ptb++){
- int len = strlen(ptb->name);
- if (strncmp(ptb->name,pt,len)==0
- && pt[len] == ':'){
- html_parsepath(pt + len + 1);
- html_submit = ptb->but;
- break;
- }
- }
- #endif
- }else{
- strcpy (file_request,intro.getpath()+strlen(USR_LIB_LINUXCONF)+1);
- strcat (file_request,".html");
- }
- html_post = is_post;
- get_ok = 1;
- }else if (stricmp(cmd,"Content-length:")==0){
- expected_length = atoi(pt);
- }else if (stricmp(cmd,"Authorization:")==0){
- char basic[1000];
- pt = str_copyword (basic,pt);
- if (stricmp(basic,"Basic")==0){
- pt = str_copyword (basic,pt);
- char pw[1000];
- base64_decode(pw,basic);
- char *ptpt = strchr(pw,':');
- if (ptpt != NULL){
- *ptpt++ = '\0';
- strcpy (username,pw);
- strcpy (password,ptpt);
- }
- }
- }
- }
- }
- return ret;
- }
-
- static void html_copy (const char *fname)
- {
- char path[PATH_MAX];
- sprintf (path,"%s/%s",USR_LIB_LINUXCONF,fname);
- if (debug) fprintf (stderr,"Sending :%s:\n",path);
- FILE *fin = fopen (path,"r");
- if (fin == NULL){
- html_printf ("500 file %s not found\r\n",fname);
- html_flush();
- }else{
- struct stat st;
- int size = -1;
- if (stat(path,&st)!=-1) size = st.st_size;
- html_sendintro(strstr(fname,".gif")!=NULL ? "image/gif" : "text/html"
- ,size,4*60*60);
- html_flush();
- char buf[10000];
- int n;
- while ((n=fread(buf,1,sizeof(buf),fin))> 0){
- //if (debug) fwrite (buf,1,n,stderr);
- write (html_cli,buf,n);
- }
- html_printf ("\r\n");
- html_flush();
- fclose (fin);
- }
- }
-
-
- static SSTRING *tbs[200];
-
- /*
- Get a command (A "get" indeed) from a client (Web browser).
- parse this command into a path that will silently show the way
- so linuxconf will silently travel to the proper menu, draw it
- and quit.
-
- Return -1 if there was some error or nothing has happen
- for a long time (no more job). Nothing to do for Linuxconf.
- */
- int html_get (int _debug, HELP_FILE &intro)
- {
- debug = _debug;
- if (cmd == NULL) cmd = new CMDSOCK (debug ? port : -1);
- int ret = -1;
- while (1){
- if (cmd->listen(600*1000000) <= 0){
- break;
- }else{
- char buf[1000];
- int nb;
- int cli;
- if ((nb=cmd->readnext (buf,sizeof(buf)-1,cli))>=0){
- if (nb == 0){
- cmd->closecli (cli);
- }else if (tbs[cli] == NULL
- && html_access_check(cli)!=0){
- html_cli = cli;
- html_printf ("500 access denied\r\n");
- html_flush();
- cmd->closecli (cli);
- }else{
- buf[nb] = '\0';
- if (tbs[cli] == NULL){
- tbs[cli] = new SSTRING;
- }
- tbs[cli]->append (buf);
- if (tbs[cli]->getlen()>10000){
- /* #Specification: html mode / input overflow
- If linuxconf receive an http request exceding
- 10000 bytes, it is silently flushed.
- */
- cmd->closecli(cli);
- delete tbs[cli];
- tbs[cli] = NULL;
- }else{
- char file_request[PATH_MAX];
- char username[50];
- char password[50];
- html_dbglog ("so far",tbs[cli]->get());
- int ok = html_parse (tbs[cli]->get(),file_request
- ,username,password,intro);
- perm_setaccess(username,password);
- if (ok == -1){
- cmd->closecli (cli);
- delete tbs[cli];
- tbs[cli] = NULL;
- }else if (ok > 0){
- html_cli = cli;
- delete tbs[cli];
- tbs[cli] = NULL;
- if (file_request[0] != '\0'){
- html_copy (file_request);
- cmd->closecli (cli);
- }else{
- ret = 0;
- break;
- }
- }
- }
- }
- }
- }
- }
- return ret;
- }
-
-
-